package cn.iocoder.yudao.module.infra.asr.impl.volcengine;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.infra.asr.AsrConfig;
import cn.iocoder.yudao.module.infra.asr.IAsrService;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

/**
 * 火山引擎
 * https://www.volcengine.com/docs/6561/80816
 */
@Service("tts-volcengine")
@Slf4j
public class VolcengineAsrServiceImpl implements IAsrService {
    private AsrConfig.Config volcengineConfig;

    @Resource
    private AsrConfig asrConfig;

    @PostConstruct
    public void init(){
        this.volcengineConfig = asrConfig.getServices().get("volcengine");
    }

    @Override
    public String audioToText(String audioFormat, InputStream fp) {
        try {
            // 将 InputStream 转换为 byte[]
            final byte[] audioData = inputStreamToByteArray(fp);

            // 调用处理 byte[] 数据的通用方法
            return audioToText(audioFormat, audioData);
        } catch (IOException e) {
            log.warn(StrUtil.format("语音识别异常, audioFormat = {}", audioFormat), e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public String audioToText(String audioFormat, byte[] audioData) {
        log.info("语音识别开始, audioFormat = {}", audioFormat);

        final String appid = volcengineConfig.getAppid();
        final String token = volcengineConfig.getToken();
        final String cluster = volcengineConfig.getCluster();

        AsrClient asr_client = null;
        try {
            asr_client = AsrClient.build();
            asr_client.setAppid(appid);
            asr_client.setToken(token);
            asr_client.setCluster(cluster);
            asr_client.setFormat(audioFormat);
            asr_client.setShow_utterances(false);
            asr_client.asr_sync_connect();

            byte[] buffer = new byte[16000];
            int lenToSend = 0;
            int offset = 0;
            AsrResponse asr_response = new AsrResponse();

            // 处理 byte[] 数据
            while (offset < audioData.length) {
                lenToSend = Math.min(buffer.length, audioData.length - offset);
                System.arraycopy(audioData, offset, buffer, 0, lenToSend);
                asr_response = asr_client.asr_send(Arrays.copyOfRange(buffer, 0, lenToSend), offset + lenToSend == audioData.length);
                offset += lenToSend;
                log.info("发送语音数据, len = {}", lenToSend);
            }

            // get asr text
            final StringBuilder sb = new StringBuilder();
            for (AsrResponse.Result result : asr_response.getResult()) {
                sb.append(result.getText());
            }
            final String text = sb.toString();
            log.info("语音识别成功, text = {}", text);
            return text;
        } catch (Exception e) {
            log.warn("语音识别异常", e);
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            throw new RuntimeException(e);
        } finally {
            if (asr_client != null) {
                asr_client.asr_close();
            }
        }
    }

    /**
     * 将 InputStream 转换为 byte[]
     */
    private byte[] inputStreamToByteArray(InputStream inputStream) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, length);
        }
        return byteArrayOutputStream.toByteArray();
    }
}
